﻿using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;

namespace Kyoh.Lib.WinForms
{
    /// <summary><see cref="IconText"/> を表示する <see cref="DataGridViewTextBoxCell"/> の拡張。</summary>
    public class DataGridViewIconTextCell : DataGridViewTextBoxCell
    {
        /// <summary>表示用に書式指定済みのセル値を取得します。</summary>
        /// <param name="value">書式設定される値。</param>
        /// <param name="rowIndex">セルの親行のインデックス。</param>
        /// <param name="cellStyle">セルに反映される <see cref="System.Windows.Forms.DataGridViewCellStyle"/>。</param>
        /// <param name="valueTypeConverter">書式指定済みの値の型へカスタムの変換を実行する、元の値の型に関連付けられた <see cref="System.ComponentModel.TypeConverter" />。カスタムの変換が不要な場合は <c>null</c>。</param>
        /// <param name="formattedValueTypeConverter">書式指定済みの値の型からカスタムの変換を実行する、その値の型に関連付けられた <see cref="System.ComponentModel.TypeConverter" />。カスタムの変換が不要な場合は <c>null</c>。</param>
        /// <param name="context">書式指定済みの値が必要とされているコンテキストを示す <see cref="System.Windows.Forms.DataGridViewDataErrorContexts"/> 値のビットごとの組み合わせ。</param>
        /// <returns>書式指定済みのセル値。または、セルが <see cref="System.Windows.Forms.DataGridView"/> コントロールに属していない場合は <c>null</c>。</returns>
        protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
        {
            var iconText = value as IconText;
            if (iconText == null)
                return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
            else
                return base.GetFormattedValue(iconText.Text, rowIndex, ref cellStyle, valueTypeConverter,
                                              formattedValueTypeConverter, context);
        }

        /// <summary>セルを描画します。</summary>
        protected override void Paint(Graphics graphics,
            Rectangle clipBounds, Rectangle cellBounds,
            int rowIndex, DataGridViewElementStates cellState,
            object value, object formattedValue, string errorText,
            DataGridViewCellStyle cellStyle,
            DataGridViewAdvancedBorderStyle advancedBorderStyle,
            DataGridViewPaintParts paintParts)
        {
            var iconText = value as IconText;
            if (iconText == null)
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue,
                           errorText, cellStyle, advancedBorderStyle, paintParts);
                return;
            }

            //セルの境界線（枠）を描画する
            if ((paintParts & DataGridViewPaintParts.Border) ==
                DataGridViewPaintParts.Border)
            {
                base.PaintBorder(graphics, clipBounds, cellBounds,
                    cellStyle, advancedBorderStyle);
            }

            //境界線の内側に範囲を取得する
            Rectangle borderRect = this.BorderWidths(advancedBorderStyle);
            Rectangle paintRect = new Rectangle(
                cellBounds.Left + borderRect.Left,
                cellBounds.Top + borderRect.Top,
                cellBounds.Width - borderRect.Right,
                cellBounds.Height - borderRect.Bottom);

            //背景色を決定する
            //選択されている時とされていない時で色を変える
            bool isSelected =
                (cellState & DataGridViewElementStates.Selected) ==
                DataGridViewElementStates.Selected;
            Color bkColor;
            if (isSelected &&
                (paintParts & DataGridViewPaintParts.SelectionBackground) ==
                    DataGridViewPaintParts.SelectionBackground)
            {
                bkColor = cellStyle.SelectionBackColor;
            }
            else
            {
                bkColor = cellStyle.BackColor;
            }
            //背景を描画する
            if ((paintParts & DataGridViewPaintParts.Background) ==
                DataGridViewPaintParts.Background)
            {
                using (SolidBrush backBrush = new SolidBrush(bkColor))
                {
                    graphics.FillRectangle(backBrush, paintRect);
                }
            }

            //Paddingを差し引く
            paintRect.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top);
            paintRect.Width -= cellStyle.Padding.Horizontal;
            paintRect.Height -= cellStyle.Padding.Vertical;

            Rectangle iconRect = new Rectangle(paintRect.Left + 1, paintRect.Top + 1, 16, 16);

            //フォーカスの枠を表示する
            if (this.DataGridView.CurrentCellAddress.X == this.ColumnIndex &&
                this.DataGridView.CurrentCellAddress.Y == this.RowIndex &&
                (paintParts & DataGridViewPaintParts.Focus) ==
                    DataGridViewPaintParts.Focus &&
                this.DataGridView.Focused)
            {
                //フォーカス枠の大きさを適当に決める
                Rectangle focusRect = paintRect;
                focusRect.Inflate(-3, -3);
                ControlPaint.DrawFocusRectangle(graphics, focusRect);
                //背景色を指定してフォーカス枠を描画する時
                //ControlPaint.DrawFocusRectangle(
                //    graphics, focusRect, Color.Empty, bkColor);
            }

            //アイコンを表示する
            if ((paintParts & DataGridViewPaintParts.ContentForeground) ==
                DataGridViewPaintParts.ContentForeground)
            {
                graphics.DrawImage(iconText.Icon, iconRect);
            }

            //テキストを表示する
            if ((paintParts & DataGridViewPaintParts.ContentForeground) ==
                DataGridViewPaintParts.ContentForeground)
            {
                //表示するテキストを決定
                string txt = iconText.Text;
                //string txt = formattedValue.ToString();

                // cellStyleによりTextFormatFlagsを決定する
                TextFormatFlags flags = TextFormatFlags.Default;
                switch (cellStyle.Alignment)
                {
                    case DataGridViewContentAlignment.BottomCenter:
                        flags = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter;
                        break;
                    case DataGridViewContentAlignment.BottomLeft:
                        flags = TextFormatFlags.Bottom | TextFormatFlags.Left;
                        break;
                    case DataGridViewContentAlignment.BottomRight:
                        flags = TextFormatFlags.Bottom | TextFormatFlags.Right;
                        break;
                    case DataGridViewContentAlignment.MiddleCenter:
                        flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
                        break;
                    case DataGridViewContentAlignment.MiddleLeft:
                        flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
                        break;
                    case DataGridViewContentAlignment.MiddleRight:
                        flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
                        break;
                    case DataGridViewContentAlignment.TopCenter:
                        flags = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter;
                        break;
                    case DataGridViewContentAlignment.TopLeft:
                        flags = TextFormatFlags.Top | TextFormatFlags.Left;
                        break;
                    case DataGridViewContentAlignment.TopRight:
                        flags = TextFormatFlags.Top | TextFormatFlags.Right;
                        break;
                }

                if (cellStyle.WrapMode == DataGridViewTriState.False)
                {
                    flags |= TextFormatFlags.SingleLine;
                    flags |= TextFormatFlags.EndEllipsis;
                }

                //色を決定
                Color fColor;
                if (isSelected)
                    fColor = cellStyle.SelectionForeColor;
                else
                    fColor = cellStyle.ForeColor;
                //テキストを描画する
                paintRect.Inflate(-11, -2);
                paintRect.Offset(9, 0);
                TextRenderer.DrawText(graphics, txt, cellStyle.Font,
                    paintRect, fColor, flags);
            }

            //エラーアイコンの表示
            if ((paintParts & DataGridViewPaintParts.ErrorIcon) ==
                DataGridViewPaintParts.ErrorIcon &&
                this.DataGridView.ShowCellErrors &&
                !string.IsNullOrEmpty(errorText))
            {
                //エラーアイコンを表示させる領域を取得
                Rectangle iconBounds = this.GetErrorIconBounds(
                    graphics, cellStyle, rowIndex);
                iconBounds.Offset(cellBounds.X, cellBounds.Y);
                //エラーアイコンを描画
                this.PaintErrorIcon(graphics, iconBounds, cellBounds, errorText);
            }
        }
    }
}
